package com.common.tools.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.common.api.exception.CommonException;
import com.common.tools.api.dto.DictItemDto;
import com.common.tools.api.service.DictItemService;
import com.common.tools.dao.DictItemMapper;
import com.common.tools.po.DictItemPo;
import com.common.tools.util.ToolsConstant;
import com.common.util.GenerateSequenceUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * <p>
 * 字典表服务实现类
 * </p>
 *
 * @author system
 */
@Slf4j
@Service
public class DictItemServiceImpl extends DictItemService {

    @Autowired
    private DictItemMapper dictItemMapper;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int dels(List<String> idList) {
        try {
            validateSelectedDictItem(idList);
            log.info("尝试删除的ID列表：{}", JSON.toJSONString(idList));
            List<DictItemPo> dictItemPos = validateSelectedDictItemByDatabase(idList);
            validateDictItemPos(dictItemPos);
            log.info("即将删除的ID列表：{}", JSON.toJSONString(idList));
            dictItemMapper.deleteBatchIds(idList);
            // 删除成功后返回1
            return 1;
        } catch (Exception e) {
            log.error("删除字典项出现异常，{}", e.getMessage());
            throw e;
        }
    }

    private List<DictItemPo> validateSelectedDictItemByDatabase(List<String> idList) {
        List<DictItemPo> dictItemPos = dictItemMapper.selectBatchIds(idList);
        if (CollectionUtils.isEmpty(dictItemPos)) {
            throw new CommonException("未查询到要删除的字典项！");
        }
        return dictItemPos;
    }

    private void validateSelectedDictItem(List<String> idList) {
        if (CollectionUtils.isEmpty(idList)) {
            throw new CommonException("请选择要删除的字典项！");
        }
    }


    private void validateDictItemPos(List<DictItemPo> dictItemPos) throws CommonException {
        dictItemPos.stream()
                .filter(dictItemPo -> isSysDictItem(dictItemPo.getDictItemCode()))
                .findAny()
                .ifPresent(dictItemPo -> {
                    String errorMsg = "不允许删除以" + ToolsConstant.SYS_DICT + "开头的字典项！";
                    log.error(errorMsg);
                    throw new CommonException(errorMsg);
                });
    }

    // 判断是否为系统字典项
    private boolean isSysDictItem(String dictCode) {
        return StringUtils.isNotBlank(dictCode) && dictCode.startsWith(ToolsConstant.SYS_DICT);
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public int add(DictItemDto dto) {
        try {
            validateAndAddDictItem(dto);
            // 新增字典值信息
            dictItemMapper.insert(dto);
            return 1;
        } catch (Exception e) {
            log.info("新增字典信息出现异常，{}", e.getMessage());
            throw e;
        }
    }


    private void validateAndAddDictItem(DictItemDto dto) {
        validateDictItemDto(dto);
        validateSysDictCode(dto.getDictItemCode());
        // 每次新增字典分类的时候，校验是否唯一
        checkDictCodeUnique(dto.getDictTypeCode(), dto.getDictItemCode());
        //新增字典分类的时候，生成ID
        prepareDictItemDto(dto);
    }

    private void prepareDictItemDto(DictItemDto dto) {
        if (StringUtils.isBlank(dto.getId())) {
            dto.setId(GenerateSequenceUtil.generateSequenceNo());
            dto.setCreateTime(new Date());
            dto.setUpdateTime(new Date());
            dto.setDictTypeCode(dto.getDictTypeCode());
        } else {
            dto.setUpdateTime(new Date());
        }
    }

    private void checkDictCodeUnique(String dictTypeCode, String dictCode) {
        boolean exists = dictItemMapper.exists(Wrappers.lambdaQuery(DictItemPo.class)
                .eq(DictItemPo::getDictItemCode, dictCode)
                .eq(DictItemPo::getDictTypeCode, dictTypeCode));
        if (exists) {
            throw new CommonException("字典项编码不能重复！");
        }
    }

    private void validateSysDictCode(String dictCode) {
        if (dictCode.startsWith(ToolsConstant.SYS_DICT)) {
            throw new CommonException("不允许设置系统字典项编码(以SYS开头的)！");
        }
    }

    private void validateDictItemDto(DictItemDto dto) {
        if (Objects.isNull(dto)) {
            throw new CommonException("字典项信息不能为空！");
        }
        validateField(dto.getDictTypeCode(), "字典分类编码");
        validateField(dto.getDictItemCode(), "字典项编码");
        validateField(dto.getDictItemValue(), "字典项值");
    }

    private void validateField(String value, String filedName) {
        if (StringUtils.isBlank(value)) {
            throw new CommonException(filedName + "不能为空！");
        }
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public int modify(DictItemDto dto) {
        try {
            validateAndUpdateDictItem(dto);
            dictItemMapper.updateById(dto);
            return 1;
        } catch (Exception e) {
            log.info("修改字典信息出现异常，{}", e.getMessage());
            throw e;
        }
    }

    private void validateAndUpdateDictItem(DictItemDto dto) {
        validateDictItemDto(dto);
        validateSysDictCode(dto.getDictItemCode());
        DictItemPo dictItemPo = checkDictItemExist(dto.getId());
        checkDictCodeModification(dto, dictItemPo);
        // 修改字典值信息
        prepareDictItemDto(dto);
    }

    private DictItemPo checkDictItemExist(String dictItemId) {
        return Optional.ofNullable(dictItemMapper.selectById(dictItemId))
                .orElseThrow(() ->  new CommonException("当前要修改的字典项不存在！"));
    }


    private void checkDictCodeModification(DictItemDto dictItemDto, DictItemPo dictItemPo) {
        checkFieldModification(dictItemPo.getDictItemCode(), dictItemDto.getDictItemCode(), "字典项编码");
    }

    private void checkFieldModification(String oldValue, String newValue, String errorMessage) {
        if (!Objects.equals(oldValue, newValue)) {
            throw new CommonException(errorMessage + "不允许修改！");
        }
    }


    @Override
    public List<String> getSearchKeyList() {
        return Arrays.asList("dict_code", "dict_value");
    }

}
